# @Time : 2024-10-28 13:34
# @Author : Fioman 
# @Phone : 13149920693
"""
类创建过程:
元类是创建类的类,当我们声明定义 class A:pass 的时候,其实就已经调用了type()函数去创建这个类对象.
默认情况下调用的是type类的__new__()函数,里面去调用type(className,bases,attrs),
假如我们实现了自定义的元类,一般自定义的元类继承自type,然后在自定义的元类里面调用super()__new__()方法,
最终还是调用type()函数
"""

if __name__ == '__main__':
    class MyClass:
        pass

# 相当于是
# MyClass = type("MyClass", (object,), {})

# 测试一下
obj = MyClass()
print(obj)
MyClass2 = type("MyClass2", (), {})
obj = MyClass2()
print(obj)


# 自定义元类,你可以通过指定metaclass参数来定义一个元类.
# 当你定义metaclass的时候,会在元类中调用type或者其超类的__new__和__init__方法
# 来创建类.

class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        print(f"Creating class {name}")
        return super().__new__(cls, name, bases, attrs)


class Simple(metaclass=MyMeta):
    pass


# 运行的时候就会调用MyMeta类的__new__方法,创建类Simple

"""
元类有什么好处呢?
1) 代码自动化,需要重复的任务可以放到元类中去执行
2) 增强一致性: 通过元类可以确保所有类遵循相同的设计模式或者约定
"""

# region 1. 自动注册类,在创建类的时候自动注册到某个全局注册表中,以便以后可以轻松引用或者管理这些类
registry = {}


class AutoRegisterMeta(type):
    def __new__(cls, name, bases, attrs):
        classObj = super().__new__(cls, name, bases, attrs)
        registry[name] = classObj
        return classObj


# 使用元类进行自动注册
class Base(metaclass=AutoRegisterMeta):
    pass


class SubClass1(Base):
    pass


class SubClass2(Base):
    pass


print(registry)


# endregion

# region 修改类属性,在创建类的时候自动修改或者添加类属性,例如为类默认添加属性值
class AttributeAddingMeta(type):
    def __new__(cls, name, bases, attrs):
        attrs["totalCount"] = 100
        return super().__new__(cls, name, bases, attrs)


class Simple2(metaclass=AttributeAddingMeta):
    pass


# 创建的类默认有一个totalCount属性
print(Simple2.totalCount)


# endregion

# region 类验证,比如类必须符合特定的条件,比如,实现特定的方法等
class ValidateMeta(type):
    def __new__(cls, name, bases, attrs):
        if "some_method" not in attrs:
            raise TypeError(f"class '{name}' must define 'some_method'")
        else:
            "create class {} successfully".format(name)
        return super().__new__(cls, name, bases, attrs)


class Simple3(metaclass=ValidateMeta):
    def some_method(self):
        pass


try:
    # 没有创建,就会报错,这里加上try之后,就不报错了
    class Simple4(metaclass=ValidateMeta):
        pass
except Exception as e:
    print(str(e))

# endregion
